import type { ComputedRef } from 'vue';

import { checkUpgrade } from '@/api/mobile';
import { isString } from '@/utils/is';
import { ErrorMessageMode } from '#/request';

import { useUpgraderStore } from './store';
import {
  AppInfo,
  UpgradeCheck,
  UpgradeInfo,
  UpgraderOptions,
  UpgraderOptionsInternal,
} from './types';

/** 默认升级检测Api */
export const defaultCheckApi = async (
  dto: UpgradeCheck,
  version: string,
  mode: ErrorMessageMode = 'modal',
): Promise<UpgradeInfo> => {
  const input = { Code: dto.Code, Platform: dto.Platform };
  let info: UpgradeInfo = null;
  const result = await checkUpgrade(input, mode);
  if (result.Type === 200 && result.Data) {
    const resultDto = result.Data;
    info = {
      need: resultDto.Enabled && resultDto.VersionCode !== version,
      force: resultDto.Force,
      silent: resultDto.Silent,

      appStoreLink: resultDto.AppStoreLink,
      wgt: resultDto.Wgt,
      version: resultDto.Version,
      versionCode: resultDto.VersionCode,
      author: resultDto.Author,
      email: resultDto.Email,

      url: resultDto.Url,

      title: resultDto.Title,
      content: resultDto.Content,
    };

    if (resultDto.Size > 0) {
      info.size = resultDto.Size;
    }
  }
  return info;
};

/**
 * Upgrader 用到的 key
 * @internal
 */
const upgraderKey = '__EA_UPGRADER_KEY__';
/** 升级程序用到的 key */
export const getUpgraderKey = (selector: string = '') => {
  return selector && isString(selector) ? `${upgraderKey}${selector.toUpperCase()}` : upgraderKey;
};

/** 使用升级程序-内部
 * @internal
 * @param selector 选择器
 * @param appInfo 应用信息
 * @param mode 错误消息提示模式
 */
export function useUpgraderInternal(
  selector: string = '',
  appInfo?: ComputedRef<AppInfo>,
  mode?: ErrorMessageMode,
) {
  /** 选择器键 */
  const selectorKey = getUpgraderKey(selector);

  const upgraderStore = useUpgraderStore();

  /** 获取选项 */
  const getOptions = computed<UpgraderOptionsInternal>(() => upgraderStore.getOptions(selectorKey));
  /** 获取应用信息 */
  const getAppInfo = computed<AppInfo>(() => upgraderStore.getAppInfo(selectorKey));
  /** 获取版本描述 */
  const getVersion = computed(() => upgraderStore.getVersion(selectorKey));
  /** 获取处理进度 */
  const getProgress = computed<OnProgressEvent>(() => upgraderStore.getProgress);

  /** 获取显示 */
  const getShow = computed(() => unref(getOptions).show);
  /** 获取标题 */
  const getTitle = computed(() => unref(getOptions).title);
  /** 获取升级信息 */
  const getUpgrade = computed(() => unref(getOptions).upgrade);
  /** 获取显示进度 */
  const getShowProgress = computed(() => unref(getOptions).showProgress);

  if (mode) {
    upgraderStore.setOptions(selectorKey, { errorMessageMode: mode });
  }

  // 监听 appInfo 变化
  watch(
    () => appInfo?.value,
    (v) => {
      if (v) {
        upgraderStore.setOptions(selectorKey, { appInfo: v });
      }
    },
    {
      deep: true,
      immediate: true,
    },
  );

  /** 检测升级
   * @param _mode 错误消息提示模式
   * @param silent 静默检测
   * @param checkApi 检查更新接口函数
   */
  async function check(
    _mode: ErrorMessageMode = mode,
    silent: boolean = false,
    checkApi: typeof defaultCheckApi = defaultCheckApi,
  ) {
    return await upgraderStore.check(selectorKey, _mode, silent, checkApi);
  }

  /** 处理升级
   * @param _mode 错误消息提示模式
   */
  async function upgrade(_mode: ErrorMessageMode = mode) {
    return await upgraderStore.upgrade(selectorKey, mode);
  }

  /** 取消升级 */
  async function abort() {
    return await upgraderStore.abort(selectorKey);
  }

  /** 设置窗口显示 */
  async function show(show: boolean) {
    return await upgraderStore.show(selectorKey, show);
  }

  /** 关闭窗口显示 */
  async function close() {
    return await upgraderStore.close(selectorKey);
  }

  return {
    /** 获取选项 */
    getOptions,
    /** 获取应用信息 */
    getAppInfo,
    /** 获取版本描述 */
    getVersion,
    /** 获取处理进度 */
    getProgress,
    /** 获取显示 */
    getShow,
    /** 获取标题 */
    getTitle,
    /** 获取升级信息 */
    getUpgrade,
    /** 获取显示进度 */
    getShowProgress,
    /** 设置选项 */
    setOptions: (options?: UpgraderOptions) => upgraderStore.setOptions(selectorKey, options),
    /** 检测升级 */
    check,
    /** 处理升级 */
    upgrade,
    /** 取消升级 */
    abort,
    /** 设置窗口显示 */
    show,
    /** 关闭窗口显示 */
    close,
  };
}
